<script setup lang="ts" name="GoodsSku">
import type { GoodsInfo, Spec, SpecValue } from "@/types/data";
import bwPowerSet from "@/utils/power-set";
import { ref, watch } from "vue"; // 1. 新增: 引入 ref 和 watch

const props = defineProps<{
  goods: GoodsInfo;
  skuId?: string;
}>();

const emit = defineEmits<{ (e: "changeSku", skuId: string): void }>();

// 2. 调整: 将 pathMap 定义为响应式变量
const pathMap = ref({} as { [key: string]: string[] });

/**
 * 获取路径字典
 */
const getPathMap = () => {
  const map: { [key: string]: string[] } = {};
  // 1. 过滤掉库存为0的sku
  const skus = props.goods.skus.filter((item) => item.inventory > 0);
  // 2. 遍历有效的sku,获取sku的幂集
  skus.forEach((item) => {
    const arr = item.specs.map((sub) => sub.valueName);
    // 3. 调用powerSet获取幂集
    const powerSet = bwPowerSet(arr);
    // 4. 把这些powerSet合并到一个路径字典中
    powerSet.forEach((sub) => {
      const key = sub.join("★");
      if (key in map) {
        map[key].push(item.id);
      } else {
        map[key] = [item.id];
      }
    });
  });
  return map;
};
// 获取选中的规格
const getSelectedSpec = () => {
  const arr: string[] = [];
  props.goods.specs.forEach((item) => {
    const temp = item.values.find((sub) => sub.selected);
    arr.push(temp ? temp.name : "");
  });
  return arr;
};

// 设置默认选中效果
const initSelectedSpec = () => {
  const sku = props.goods.skus.find((item) => item.id === props.skuId);
  if (sku) {
    props.goods.specs.forEach((item, index) => {
      item.values.forEach((sub) => (sub.selected = false));
      const select = sku.specs[index].valueName;
      const sub = item.values.find((sub) => sub.name === select)!;
      sub.selected = true;
    });
  }
};
// 更新按钮的禁用状态
const updateDisabledStatus = () => {
  props.goods.specs.forEach((item, index) => {
    item.values.forEach((sub) => {
      // 核心改动: 在每次检查一个值时，都重新获取一个当前选中的规格数组
      const selectedSpec = getSelectedSpec();

      if (sub.selected) {
        sub.disabled = false;
        return;
      }

      selectedSpec[index] = sub.name;
      const key = selectedSpec.filter((v) => v).join("★");

      // 3. 调整: 使用 .value 访问响应式变量
      if (key in pathMap.value) {
        sub.disabled = false;
      } else {
        sub.disabled = true;
      }
    });
  });
};

/**
 * 选中规格
 */
const changeSelected = (item: Spec, sub: SpecValue) => {
  if (sub.disabled) return;
  if (sub.selected) {
    sub.selected = false;
  } else {
    item.values.forEach((v) => (v.selected = false));
    sub.selected = true;
  }
  updateDisabledStatus();

  const selected = getSelectedSpec().filter((v) => v);
  if (selected.length === props.goods.specs.length) {
    const key = selected.join("★");

    // 4. 调整: 使用 .value 访问响应式变量
    const skus = pathMap.value[key];

    // 5. 调整: 添加检查，确保 skus 存在
    if (skus) {
      const [skuId] = skus;
      emit("changeSku", skuId);
    } else {
      emit("changeSku", "");
    }
  } else {
    emit("changeSku", "");
  }
};

// 6. 核心改动: 使用 watch 监听 props.goods，确保在数据加载完成后才执行初始化
watch(
  () => props.goods,
  (newVal) => {
    if (newVal && newVal.skus) {
      pathMap.value = getPathMap(); // 重新生成 pathMap
      initSelectedSpec();
      updateDisabledStatus();
    }
  },
  {
    immediate: true, // 立即执行一次，以处理初次加载
  }
);
</script>
<template>
  <div class="goods-sku">
    <!-- 一个规格 -->
    <dl v-for="item in goods.specs" :key="item.name">
      <dt>{{ item.name }}</dt>
      <dd>
        <!-- 一个规格有多个值 -->
        <template v-for="sub in item.values" :key="sub.name">
          <img
            @click="changeSelected(item, sub)"
            v-if="sub.picture"
            :src="sub.picture"
            alt=""
            :title="sub.name"
            :class="{ selected: sub.selected, disabled: sub.disabled }"
          />
          <span
            :class="{ selected: sub.selected, disabled: sub.disabled }"
            @click="changeSelected(item, sub)"
            v-else
            >{{ sub.name }}</span
          >
        </template>
      </dd>
    </dl>
  </div>
</template>

<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;
  &.selected {
    border-color: @sealColor;
  }
  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}
.goods-sku {
  padding-left: 10px;
  padding-top: 20px;
  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;
    dt {
      width: 50px;
      color: #999;
    }
    dd {
      flex: 1;
      color: #666;
      > img {
        width: 50px;
        height: 50px;
        margin-top: 5px;
        .sku-state-mixin ();
      }
      > span {
        display: inline-block;
        height: 30px;
        line-height: 30px;
        padding: 0 20px;
        margin-top: 5px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
